package cn.hist.hfp.service;

import cn.hist.hfp.converter.BusinessProviderConverter;
import cn.hist.hfp.entity.Business;
import cn.hist.hfp.entity.BusinessProvider;
import cn.hist.hfp.exception.ResourceNotFoundException;
import cn.hist.hfp.repository.BusinessProviderRepository;
import cn.hist.hfp.vo.BusinessProviderVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;

@Service
public class BusinessProviderService {

    @Value(value = "${hfp.page-size.business}")
    private int pageSize;

    private final
    BusinessProviderRepository businessProviderRepository;

    private final
    BusinessService businessService;

    private final BusinessProviderConverter businessProviderConverter;

    @Autowired
    public BusinessProviderService(BusinessProviderRepository businessProviderRepository, BusinessService businessService, BusinessProviderConverter businessProviderConverter) {
        this.businessProviderRepository = businessProviderRepository;
        this.businessService = businessService;
        this.businessProviderConverter = businessProviderConverter;
    }

    public BusinessProvider create(BusinessProvider businessProvider) {
        refreshBusinessOfProvider(businessProvider);
        return businessProviderRepository.save(businessProvider);
    }

    public BusinessProvider findOne(int id) {
        Optional<BusinessProvider> optionalBusinessProvider = businessProviderRepository.findById(id);
        if (optionalBusinessProvider.isPresent()) {
            return optionalBusinessProvider.get();
        }
        throw new ResourceNotFoundException();
    }

    public List<BusinessProviderVO> findSome(String city, int business_id, int page) {
        Pageable pageable = PageRequest.of(page, pageSize);
        if (city.equals("")) {
            if (business_id < 0) {
                return businessProviderConverter.convert(businessProviderRepository.findAll());
            }
            return businessProviderConverter.convert(businessProviderRepository
                        .findAllByBusinesses(businessService.findOne(business_id), pageable).getContent());
        }

        if (business_id < 0) {
            return businessProviderConverter.convert(businessProviderRepository.findAllByCity(city, pageable).getContent());
        }
        Business business = businessService.findOne(business_id);
        return businessProviderConverter.convert(businessProviderRepository.findAllByCityAndBusinesses(city, business, pageable).getContent());

    }

    public int numberOfPages(String city, int business_id) {
        int number;
        if (business_id < 0)
            number =  businessProviderRepository.findAllByCity(city, PageRequest.of(0, pageSize)).getTotalPages();
        else {
            Business business = businessService.findOne(business_id);
            number = businessProviderRepository.
                    findAllByCityAndBusinesses(city, business, PageRequest.of(0, pageSize)).getTotalPages();
        }
        return number <= 0 ? 1 : number;
    }

    public BusinessProvider update(BusinessProvider businessProvider) {
        refreshBusinessOfProvider(businessProvider);
        return businessProviderRepository.save(businessProvider);
    }

    public BusinessProvider addBusiness(int business_provider_id, int business_id) {
        BusinessProvider businessProvider = findOne(business_provider_id);
        Business business = businessService.findOne(business_id);
        business.getBusinessProviders().add(businessProvider);
        businessProvider.getBusinesses().add(business);
        return businessProviderRepository.save(businessProvider);
    }

    public BusinessProvider deleteBusiness(int business_provider_id, int business_id) {
        BusinessProvider businessProvider = findOne(business_provider_id);
        Business business = businessService.findOne(business_id);
        business.getBusinessProviders().remove(businessProvider);
        businessProvider.getBusinesses().remove(business);
        return businessProviderRepository.save(businessProvider);
    }

    public int delete(int id) {
        Optional<BusinessProvider> optionalBusinessProvider = businessProviderRepository.findById(id);
        optionalBusinessProvider.ifPresent(businessProviderRepository::delete);
        return businessProviderRepository.findById(id).isPresent() ? 0 : 1;
    }

    private void refreshBusinessOfProvider(BusinessProvider businessProvider) {
        if (businessProvider.getBusinesses().size() <= 0)
            return;
        Set<Business> refreshedBusinesses = new HashSet<>();
        for (Business business: businessProvider.getBusinesses()) {
            Business persistedBusiness = businessService.findOne(business.getId());
            persistedBusiness.getBusinessProviders().add(businessProvider);
            refreshedBusinesses.add(businessService.update(persistedBusiness));
        }
        businessProvider.setBusinesses(refreshedBusinesses);
    }
}
